﻿Imports System
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Drawing

Public Class Generator
    ' URL to Vash API
    Const API_URL As String = "https://www.thevash.com/api/"

    ' Hold API Account id
    Private _key As String

    ''' <summary>
    ''' Create a new instance of Vash.Net
    ''' </summary>
    ''' <param name="accountId">Your account id as provided by Zettabyte Storage</param>
    Sub New(ByVal accountId As String)
        ' Set Account Id
        _key = accountId

    End Sub

#Region " Required Properties "

    ' Use fast algorithm by default
    Private _algorithm As String = "1-fast"

    ''' <summary>
    ''' Algorithm used to create your image
    ''' </summary>
    ''' <remarks>NVash uses the Fast algorithm by default.</remarks>
    Public Property Algorithm() As AlgorithmType
        Get
            Select Case _algorithm
                Case "1"
                    Return AlgorithmType.ALG_1
                Case "1-fast"
                    Return AlgorithmType.ALG_1Fast
            End Select
        End Get
        Set(ByVal value As AlgorithmType)
            Select Case value
                Case AlgorithmType.ALG_1
                    _algorithm = "1"
                Case AlgorithmType.ALG_1Fast
                    _algorithm = "1-fast"
            End Select
        End Set
    End Property

#End Region

#Region " Optional Properties "
    Private _width As Integer = 128
    Private _height As Integer = 128
    Private _salt As String
    Private _format As String = "png"

    ''' <summary>
    ''' Desired width of the generated Vash image
    ''' </summary>
    ''' <value>Any integer from 4 to 1024</value>
    ''' <remarks>128 used by default</remarks>
    Public Property Width() As Integer
        Get
            Return _width
        End Get
        Set(ByVal value As Integer)
            If value < 4 Or value > 1024 Then
                Throw New Exception("Image width out of range. Values from 4 to 1024 are supported")
            End If
            _width = value
        End Set
    End Property

    ''' <summary>
    ''' Desired height of the generated Vash image
    ''' </summary>
    ''' <value>Any integer from 4 to 1024</value>
    ''' <remarks>128 used by default</remarks>
    Public Property Height() As Integer
        Get
            Return _height
        End Get
        Set(ByVal value As Integer)
            If value < 4 Or value > 1024 Then
                Throw New Exception("Image height out of range. Values from 4 to 1024 are supported")
            End If
            _height = value
        End Set
    End Property

    ''' <summary>
    ''' An optional cryptographic salt value. Providing a salt will change the generated Vash image.
    ''' </summary>
    Public Property InputSalt() As String
        Get
            Return Convert.FromBase64String(_salt).ToString
        End Get
        Set(ByVal value As String)
            _salt = Convert.ToBase64String(Encoding.UTF8.GetBytes(value))
        End Set
    End Property

    ''' <summary>
    ''' The format of the generated Vash image. Currently, "png", "jpeg", and "bmp" are available.
    ''' </summary>
    ''' <remarks>NVash uses PNG by default</remarks>
    Public Property OutputFormat() As ImageFormat
        Get
            Return System.Enum.Parse(GetType(ImageFormat), _format)
        End Get
        Set(ByVal value As ImageFormat)
            _format = value.ToString
        End Set
    End Property
#End Region

    Private Function GetPostData(ByVal inputData As Byte()) As Byte()
        ' Create a string builder to combine all POST data
        Dim postDataBuilder As New StringBuilder

        ' Use string builder to concatenate all arguments
        With postDataBuilder
            ' Required arguments
            .Append("account-id=" & _key)
            .Append("&algorithm-id=" & _algorithm)
            .Append("&input-data=" & Convert.ToBase64String(inputData))

            ' Optional arguments
            .Append("&width=" & _width)
            .Append("&height=" & _height)
            .Append("&output-format=" & _format)

            ' only include salt if it has been provided
            If _salt IsNot Nothing Then .Append("&input-salt=" & _salt)

        End With

        ' Finally encode into UTF8 byte array and return
        Return Encoding.UTF8.GetBytes(postDataBuilder.ToString)

    End Function

    ''' <summary>
    ''' Generate Vash image from inputData.
    ''' <example>Dim vash As New NVash.Generator("xxxx-xxxx-xxxx-xxxx")
    ''' vash.GetImage("Test Data").Save("output.png")</example>
    ''' </summary>
    ''' <param name="inputData">String containing data to use for the generation of the Vash image.</param>
    ''' <returns>Generated Vash image</returns>
    Function GetImage(ByVal inputData As String) As Image
        Return GenerateImage(Encoding.UTF8.GetBytes(inputData))
    End Function

    ''' <summary>
    ''' Generate Vash image from inputData.
    ''' <example>Dim vash As New NVash.Generator("xxxx-xxxx-xxxx-xxxx")
    ''' vash.GetImage("Test Data").Save("output.png")</example>
    ''' </summary>
    ''' <param name="inputData">Byte array of data to use for the generation of the Vash image.</param>
    ''' <returns>Generated Vash image</returns>
    Function GetImage(ByVal inputData() As Byte) As Image
        Return GenerateImage(inputData)
    End Function

    ''' <summary>
    ''' Private function used to submit the API request
    ''' </summary>
    Private Function GenerateImage(ByVal inputData() As Byte) As Image
        ' Create a POST WebRequest for the API call.
        Dim request As WebRequest = WebRequest.Create(API_URL)
        request.Method = "POST"

        ' Set the ContentType.
        request.ContentType = "application/x-www-form-urlencoded"

        ' Create POST data and convert it to a byte array.
        Dim byteArray As Byte() = GetPostData(inputData)

        ' Set the ContentLength property of the WebRequest.
        request.ContentLength = byteArray.Length

        ' Get the request stream.
        Dim dataStream As Stream = request.GetRequestStream()

        ' Write the data to the request stream.
        dataStream.Write(byteArray, 0, byteArray.Length)

        ' Close the Stream object.
        dataStream.Close()

        Dim response As WebResponse
        ' Get the response.
        response = request.GetResponse()

        ' Get the stream containing content returned by the server.
        dataStream = response.GetResponseStream()

        ' Save the stream into an image.
        Dim vashImg As Drawing.Image = Drawing.Image.FromStream(dataStream)

        ' Clean up the streams.
        dataStream.Close()
        response.Close()

        Return vashImg
    End Function

End Class
